Android 11 调用系统图片裁剪后,图片保存不了的解决方案 您所在的位置:网站首页 小米手机图片保存时发生错误 保存失败怎么解决 Android 11 调用系统图片裁剪后,图片保存不了的解决方案

Android 11 调用系统图片裁剪后,图片保存不了的解决方案

2023-10-06 22:37| 来源: 网络整理| 查看: 265

升级SDK30之后,一步一个坑。走不完的路,填不完的坑。

Android11存储机制变更:developer.android.com/about/versi…

一、遇到的问题

调用系统相册选取照片,然后裁剪,存储裁剪之后的照片,显示并上传服务器。多么正常的操作流程,相信大家都已经用过或者正在用。SDK升级到30,在Android11 上就失灵了。What?都知道是存储问题,怎么解决。现在告诉你。

二、解决思路 1、申请MANAGE_EXTERNAL_STORAGE最高的文件读取权限(一般不用) 2、通过 MediaStore API操作(我的选择) 1、SDK>=30 因为系统裁剪不能访问App的私有路径, 所以File 保存到公有路径Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES) 2、SDK= Build.VERSION_CODES.R) { if (FileUtils.uri != null) { // 通过存储的uri 查询File imageCropFile = FileUtils.getCropFile(this, FileUtils.uri); GlideUtils.loadLocalImage(this, FileUtils.uri, -1, iv_avatar); } } else { GlideUtils.loadLocalImage(this, imageCropFile.getAbsolutePath(), -1, iv_avatar); } } } 2、打开系统相册 Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, REQUEST_CODE_ALBUM); 3、打开系统裁剪 private void gotoCrop(Uri sourceUri) { imageCropFile = FileUtils.createImageFile(this, true); if (imageCropFile != null) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); //X方向上的比例 intent.putExtra("aspectY", 1); //Y方向上的比例 intent.putExtra("outputX", 256); //裁剪区的宽 intent.putExtra("outputY", 256); //裁剪区的高 intent.putExtra("scale ", true); //是否保留比例 intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.setDataAndType(sourceUri, "image/*"); //设置数据源 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { intent.putExtra(MediaStore.EXTRA_OUTPUT, FileUtils.uri); } else { Uri imgCropUri = Uri.fromFile(imageCropFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, imgCropUri); } startActivityForResult(intent, REQUEST_CODE_CAPTURE_CROP); } } 4、生成本地File(重要) public static File getAppRootDirPath() { return GlobalService.getAppContext().getExternalFilesDir(null).getAbsoluteFile(); } public static Uri uri; public static File createImageFile(Context context,boolean isCrop) { try { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String fileName = ""; if (isCrop) { fileName = "IMG_"+timeStamp+"_CROP.jpg"; } else { fileName = "IMG_"+timeStamp+".jpg"; } File rootFile = new File(getAppRootDirPath() + File.separator + "capture"); if (!rootFile.exists()) { rootFile.mkdirs(); } File imgFile; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { imgFile = new File(Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES) + File.separator + fileName); // 通过 MediaStore API 插入file 为了拿到系统裁剪要保存到的uri(因为App没有权限不能访问公共存储空间,需要通过 MediaStore API来操作) ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath()); values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); }else { imgFile = new File(rootFile.getAbsolutePath() + File.separator + fileName); } return imgFile; } catch (Exception e) { e.printStackTrace(); return null; } } 5、通过存储的Uri获取File 是不是有疑问 imageCropFile 这个File干啥的 --- 我用来上传服务器用的😭 public static File getCropFile(Context context,Uri uri){ String[] proj = { MediaStore.Images.Media.DATA }; Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null); if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); String path = cursor.getString(columnIndex); cursor.close(); return new File(path); } return null; }

仅供参考。如有建议和意见,请及时沟通。🙏



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有